package net.sudot.chess.business.controller.web;

import net.sudot.chess.business.controller.AbstractBaseController;
import net.sudot.chess.business.dto.CustomerDetailDTO;
import net.sudot.chess.business.model.Customer;
import net.sudot.chess.business.model.Room;
import net.sudot.chess.business.model.WechatGroup;
import net.sudot.chess.business.service.CustomerService;
import net.sudot.chess.business.service.GameRankLimitService;
import net.sudot.chess.business.service.RoomService;
import net.sudot.chess.business.service.SocialUserService;
import net.sudot.chess.business.service.WechatBotService;
import net.sudot.chess.business.service.WechatGroupService;
import net.sudot.chess.business.wechat.api.WechatApiService;
import net.sudot.chess.business.wechat.config.WechatProperties;
import net.sudot.chess.constant.PermissionConstants;
import net.sudot.chess.util.WBihuizhiUtils;
import net.sudot.commons.pagination.PageRequest;
import net.sudot.commons.security.LoginUser;
import net.sudot.commons.utils.ResponseMessage;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 房间
 *
 * @author tangjialin on 2018-03-03.
 */
@Controller
@RequestMapping(value = "/room")
public class RoomController extends AbstractBaseController {

    @Resource
    private WechatProperties wechatProperties;
    @Resource
    private RoomService roomService;
    @Resource
    private CustomerService customerService;
    @Resource
    private GameRankLimitService gameRankLimitService;
    @Resource
    private SocialUserService socialUserService;
    @Resource
    private WechatApiService wechatApiService;
    @Resource
    private WechatGroupService wechatGroupService;
    @Resource
    private WechatBotService wechatBotService;

    /**
     * 房间首页
     *
     * @return 返回房间视图
     */
    @GetMapping("/chat")
    public String chat() {
        if (SecurityUtils.getSubject().isPermitted(PermissionConstants.GAME_ROOM_MANAGE)) {
            throw new AuthorizationException();
        }
        return "room/chat";
    }

    /**
     * 房间首页
     *
     * @param roomId 房间ID
     * @return 返回房间视图
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_MANAGE)
    @GetMapping("/chat/{roomId}")
    public String chat(@PathVariable("roomId") Long roomId) {
        return "room/manage/chat";
    }

    /**
     * 游戏管理员房间列表
     *
     * @return 返回游戏管理员房间列表视图
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_MANAGE)
    @GetMapping("/manage")
    public String manage() {
        return "room/manage/list";
    }

    /**
     * 房间状态
     *
     * @return 返回房间状态
     */
    @PostMapping("/status")
    @ResponseBody
    public Map<String, String> status() {
        Map<String, String> statusMapping = new HashMap<>();
        for (Room.Status status : Room.Status.values()) {
            statusMapping.put(status.name(), status.memo());
        }
        return statusMapping;
    }

    /**
     * 获取房间玩家信息
     *
     * @param roomId 房间主键
     * @return 返回房间玩家信息
     */
    @PostMapping("/players/{roomId}")
    @ResponseBody
    public List<CustomerDetailDTO> players(@PathVariable("roomId") Long roomId) {
        List<CustomerDetailDTO> customerList = customerService.findListDetailByRoom(roomId);
        return customerList;
    }

    /**
     * 获取客户正在参与的房间详细信息
     *
     * @param customer 登录客户信息
     * @return 返回客户正在参与的房间详细信息
     */
    @PostMapping("/detail")
    @ResponseBody
    public Room detail(@LoginUser Customer customer) {
        if (SecurityUtils.getSubject().isPermitted(PermissionConstants.GAME_ROOM_MANAGE)) {
            throw new AuthorizationException();
        }
        List<Room> roomList = roomService.findListOpenByCustomer(customer.getId());
        return roomList.isEmpty() ? null : roomList.get(0);
    }

    /**
     * 获取等待中的房间信息
     *
     * @param gameId 游戏主键
     * @return 返回房间信息
     */
    @PostMapping("/detail/{gameId}/status-wait")
    @ResponseBody
    public Room findWaitByGame(@PathVariable("gameId") Long gameId) {
        return roomService.findWaitByGame(gameId);
    }

    /**
     * 获取房间信息
     *
     * @param roomId 房间主键
     * @return 返回房间信息
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_MANAGE)
    @PostMapping("/detail/{roomId}")
    @ResponseBody
    public Room detail(@PathVariable("roomId") Long roomId) {
        return roomService.find(roomId);
    }

    /**
     * 获取客服管理的未关闭的房间
     *
     * @param customer 登录的客服人员信息
     * @return 返回聊天信息
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_MANAGE)
    @PostMapping("/list/open")
    @ResponseBody
    public List<Room> open(@LoginUser Customer customer) {
        return roomService.findListOpenByCustomer(customer.getId());
    }

    /**
     * 获取客户参与且已结束的房间
     *
     * @param customer 登录的客户信息
     * @return 返回房间信息
     */
    @PostMapping("/list/complete")
    @ResponseBody
    public List<Room> complete(@RequestBody PageRequest pageRequest, @LoginUser Customer customer) {
        return roomService.findListCompleteByCustomer(pageRequest, customer.getId());
    }

    /**
     * 加入房间
     *
     * @param customer 玩家信息
     * @param room     房间信息
     *                 id:房间主键
     *                 gameId:游戏主键
     * @return 返回加入结果
     */
    @PostMapping("/join")
    @ResponseBody
    public ResponseEntity<String> join(@LoginUser Customer customer, @RequestBody Room room) {
        if (customer.isGameMaster()) {
            return ResponseEntity.unprocessableEntity().body("游戏管理员不能加入游戏");
        }
        if (StringUtils.isEmpty(customer.getQrcode())) {
            return ResponseEntity.unprocessableEntity().header(HttpHeaders.LOCATION, "/customer/qrcode").body("为了正常平稳的游戏体验，请前往个人中心上传二维码");
        }
        boolean exist = gameRankLimitService.exist(room.getGameId(), customer.getRank());
        if (!exist) { return ResponseEntity.unprocessableEntity().body("此游戏与您的等级不符,无法加入游戏"); }
//        SocialUser socialUser = socialUserService.findByUser(wechatApiService.getWxMpConfigStorage().getAppId(), customer.getId());
//        if (socialUser == null || !socialUser.isSubscribe()) {
//            // 未关注公众号,不能发送模板通知消息
//            return responseMessage.setCode(1).setMessage("为了及时通知您游戏进度,请先关注公众号").setData(wechatProperties.getHome());
//        }
        Long gameId = room.getGameId();
        if (gameId == null) { return ResponseEntity.badRequest().body("缺少参数"); }
        roomService.join(room, customer);
        return ResponseEntity.ok().build();
    }

    /**
     * 退出房间
     *
     * @param customer 玩家信息
     * @param room     房间信息
     *                 id:房间主键
     * @return 返回退出结果
     */
    @PostMapping("/exit")
    @ResponseBody
    public ResponseEntity<String> exit(@LoginUser Customer customer, @RequestBody Room room) {
        if (customer.isGameMaster()) {
            return ResponseEntity.unprocessableEntity().body("游戏管理员不能退出游戏");
        }
        Long roomId = room.getId();
        room = roomId == null ? null : roomService.find(roomId);
        if (room == null) { return ResponseEntity.unprocessableEntity().body("房间不存在,请返回游戏大厅重新进入"); }
        if (room.getStatus() != Room.Status.WAIT) {
            return ResponseEntity.unprocessableEntity().body("游戏已开始或已结束,不能退出");
        }
        roomService.exit(room, customer);
        return ResponseEntity.ok().build();
    }

    /**
     * 分配房号
     *
     * @param room 房间信息
     *             id:房间主键
     * @return 返回修改结果
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_ALLOCATION)
    @PostMapping("/allocation")
    @ResponseBody
    public ResponseMessage allocation(@RequestBody Room room) {
        ResponseMessage responseMessage = new ResponseMessage();
        Long roomId = room.getId();
        Room existRoom = roomId == null ? null : roomService.find(roomId);
        if (existRoom == null) { return responseMessage.setMessage("房间不存在"); }
        if (existRoom.getStatus() != Room.Status.PLAYING) { return responseMessage.setMessage("游戏未开始或已结束"); }
        // 根据gameId查询可分配的微信群名称
        WechatGroup wechatGroup = wechatGroupService.findUnUseByGame(existRoom.getGameId());
        String wechatGroupName = Optional.ofNullable(wechatGroup).map(WechatGroup::getName).orElse("");
        if (StringUtils.isEmpty(wechatGroupName)) {
            return responseMessage.setMessage("已没有可分配的微信群");
        }
        try {
            wechatGroupService.update(wechatGroup.setUsed(true));
            roomService.update(existRoom.setWechatGroupId(wechatGroup.getId()).setWechatGroupName(wechatGroupName));
            responseMessage.setSuccess(true);
            wechatBotService.sendOpenRoomCommand(wechatGroupName);
        } catch (Exception e) {
            responseMessage.setMessage("房号更新失败");
            logger.error("群信息发送失败", e);
        }
        return responseMessage;
    }

    /**
     * 修改房间信息
     *
     * @param room 房间信息
     *             id:房间主键
     *             sn:新的房号
     * @return 返回修改结果
     */
    @RequiresPermissions(value = PermissionConstants.GAME_ROOM_ALLOCATION)
    @PostMapping("/update")
    @ResponseBody
    public ResponseMessage update(@RequestBody Room room) {
        ResponseMessage responseMessage = new ResponseMessage();
        Long roomId = room.getId();
        String roomUrl = Optional.ofNullable(room.getUrl()).map(String::trim).orElse(null);
        if (!WBihuizhiUtils.validateUrl(roomUrl)) {
            return responseMessage.setMessage("房间链接格式错误");
        }
        Room existRoom = roomId == null ? null : roomService.find(roomId);
        if (existRoom == null) { return responseMessage.setMessage("房间不存在"); }
        if (existRoom.getStatus() != Room.Status.PLAYING) { return responseMessage.setMessage("游戏未开始或已结束"); }
        existRoom.setUrl(roomUrl);

        String roomSn = WBihuizhiUtils.getRoomSn(WBihuizhiUtils.getHtml(roomUrl));
        if (roomSn != null) {
            existRoom.setSn(roomSn);
            roomService.update(existRoom);
            return responseMessage.setSuccess(true);
        }
        return responseMessage.setMessage("房号更新失败");
    }

}
